<?php
/**
 * Created by PhpStorm.
 * User: dreamy
 * Date: 2019-05-25
 * Time: 11:16
 */
namespace common\services;

use common\models\TallyCategory;
use Yii;
use yii\helpers\ArrayHelper;
use yii\helpers\Json;

/**
 * Class TallyCategoryService
 * @package common\services
 * 账目分类管理
 */
class TallyCategoryService extends BaseService
{
    /**
     * 缓存存储KEY
     */
    const CACHE_BUCKET = 'TallyCategory:';

    /**
     * 缓存存储KEY
     */
    const CACHE_BUCKET_GLOBAL = 'TallyCategoryGlobal:';

    /**
     * 缓存有效期
     */
    const CACHE_TIMEOUT = 3600;

    // 挂账类别开关
    const GZ_SWITCH = true;

    /**
     * @param $id integer 分类id
     * @param $uid integer 用户id
     * @param $field string 分类字段
     * @return string
     * 根据Id 获取分类名称
     */
    public static function getTitleFromUserScope($id,$uid,$field='title')
    {
        $list = self::getListAllByUid($uid);
        $foundKey = array_search($id, array_column($list, 'id'));
        return isset($list[$foundKey]) ? ArrayHelper::getValue($list[$foundKey],$field) : null;
    }

    /**
     * @param $id
     *
     * @return mixed
     * @throws \yii\base\InvalidConfigException
     * @desc 获取分类信息 有缓存数据
     */
    public static function getCateInfoById($id)
    {
        // 先从缓存里尝试命中
        $redis = Yii::$app->get('redis');
        $cacheCategory = $redis->get(self::CACHE_BUCKET_GLOBAL.$id);
        if($cacheCategory) {
            return Json::decode($cacheCategory,JSON_UNESCAPED_UNICODE) ;
        }
        // 从DB获取
        $category = TallyCategory::find()
            ->where(['id'=>$id])
            ->limit(1)
            ->asArray()
            ->one();
        if(!$category) return null;
        // 写入缓存
        $redis->setex(self::CACHE_BUCKET_GLOBAL.$id,self::CACHE_TIMEOUT,Json::encode($category));
        return $category ;
    }

    /**
     * @throws
     * @param $id
     * @return mixed
     * @desc 根据类别ID获取类别上级ID
     */
    public static function getPidGlobal($id)
    {
        $cate = self::getCateInfoById($id);
        return ArrayHelper::getValue($cate,'pid',0);
    }

    /**
     * @throws
     * @param $id
     * @return mixed
     * @desc 根据类别ID获取类别名称 不校验权限
     */
    public static function getTitleGlobal($id)
    {
        // 先检查是否为应收付类别
        $cateTitle = TallyCategory::getGzCateName($id);
        if($cateTitle) {
            return $cateTitle;
        }
        $cate = self::getCateInfoById($id);
        return ArrayHelper::getValue($cate,'title','');
    }

    /**
     * @param $uid
     * @throws \yii\base\InvalidConfigException
     * @notes 清除分类缓存 在分类信息变动后执行
     */
    public static function clearCache($uid)
    {
        // 先从缓存里尝试命中
        $redis = Yii::$app->get('redis');
        $redis->del(self::CACHE_BUCKET.$uid);
    }

    /**
     * @param $uid
     * @param array $condition
     * @throws
     * @return array|\yii\db\ActiveRecord[]
     */
    public static function getListAllByUid($uid,$condition=[])
    {
        // 先从缓存里尝试命中
        $redis = Yii::$app->get('redis');
        $cacheCategory = $redis->get(self::CACHE_BUCKET.$uid);
        if(!empty($cacheCategory)) {
            $cacheCategory = json_decode($cacheCategory,true);
            return $cacheCategory ;
        }
        // 查表获取
        $where = [
            'uid'   => $uid,
            'status'=> TallyCategory::STATUS_VALID
        ];
        // 上级分类 默认主分类
        // $where['pid'] = ArrayHelper::getValue($condition,'pid',0) ;
        if(ArrayHelper::getValue($condition,'type')){
            $where['type'] = $condition['type'] ; // 收入or支出
        }
        // 从DB获取
        $categoryList = TallyCategory::find()
            ->select('id,title,pid,type,pic')
            ->where($where)
            ->limit(200)
            ->asArray()
            ->all();
        if(!empty($categoryList)) {
            // 写入缓存
            $redis->setex(self::CACHE_BUCKET.$uid,self::CACHE_TIMEOUT,json_encode($categoryList,JSON_UNESCAPED_UNICODE));
        }
        return $categoryList ;
    }

    /**
     * @param $uid
     * @param array $condition
     * @return array
     * 获取用户所有分类并进行父级绑定
     */
    public static function getListTreeByUid($uid,$condition=[])
    {
        $categoryList = TallyCategory::find()
            ->select('id,title,pid,type,pic,is_sys')
            ->where([
                'uid'=> $uid,
                'tally_id'  => ArrayHelper::getValue($condition,'tally_id',1),
                'status'=> TallyCategory::STATUS_VALID,
                'type'  => ArrayHelper::getValue($condition,'type',1)
            ])
            ->orWhere([
                'is_sys' => 1,
                'type'  => ArrayHelper::getValue($condition,'type',1)
            ])
            ->limit(200)
            ->orderBy('id asc')
            ->asArray()
            ->all();
        return self::mixFormat($categoryList) ;
    }

    /**
     * @param $tallyId
     * @param array $condition
     * @return array
     * 获取用户所有分类并进行父级绑定
     */
    public static function getListTreeByTallyId($tallyId,$condition=[])
    {
        $cateType = ArrayHelper::getValue($condition,'type',1);
        $categoryList = TallyCategory::find()
            ->select('id,title,pid,type,pic,is_sys')
            ->where([
                'tally_id'  => $tallyId,
                'status'=> TallyCategory::STATUS_VALID,
                'type'  => $cateType
            ])
//            ->orWhere([
//                'is_sys' => 1,
//                'type'  => ArrayHelper::getValue($condition,'type',1)
//            ])
            ->limit(200)
            ->orderBy('id asc')
            ->asArray()
            ->all();
        $orgList = self::mixFormat($categoryList);
        // 判断挂账开关是否开启
        if(self::GZ_SWITCH) {
            if($cateType == 1)  $orgList[] = TallyCategory::$ysExt;
            if($cateType == 2)  $orgList[] = TallyCategory::$yfExt;
        }
        return $orgList;
    }

    /**
     * @param $formData
     * @return bool
     */
    public static function create($formData)
    {
        $model = new TallyCategory();
        $model->load($formData,'');
        if ($model->validate() && $model->save()) {
            return $model->id ;
        }else{
            Yii::error('TallyCategory insert error:'.current($model->getFirstErrors()).';post:'.Json::encode($formData,JSON_UNESCAPED_UNICODE));
            self::setError(current($model->getFirstErrors()));
            return false;
        }
    }

    /**
     * @param $condition
     * @param $formData
     * @return bool
     */
    public static function update($condition,$formData)
    {
        $model = TallyCategory::find()->where($condition)->one();
        if(!$model){
            self::setError('分类不存在');
            return false ;
        }
        $model->load($formData,'');
        if ($model->validate() && $model->save()) {
            return true ;
        }else{
            Yii::error('TallyCategory update error:'.current($model->getFirstErrors()).';post:'.Json::encode($formData,JSON_UNESCAPED_UNICODE));
            self::setError(current($model->getFirstErrors()));
            return false;
        }
    }

    /**
     * @param $condition
     * @return bool
     * @throws
     */
    public static function delete($condition)
    {
        $model = TallyCategory::find()->where($condition)->one();
        if(!$model){
            self::setError('分类不存在');
            return false ;
        }
        $model->status = TallyCategory::STATUS_INVALID;
        if ($model->delete()) {
            if($condition['id'] > 1000 ){
                // 删除下级分类 加上条件 防止误删系统关联
                TallyCategory::updateAll(['status' => TallyCategory::STATUS_INVALID],[
                    'pid' => $condition['id'],
                    'tally_id' => $condition['tally_id'],
                ]);
            }
            return true ;
        }else{
            self::setError(current($model->getFirstErrors()));
            return false;
        }
    }

    /**
     * @param $action
     * @param int $parent_id
     * @return array
     * 递归获取友好展示
     */
    private static function mixFormat($action, $parent_id = 0)
    {
        $tmp = [];
        foreach ($action as $k => $v) {
            if ($v['pid'] == $parent_id) {
                $tmp[] = $v;
                unset($action[$k]);
            }
        }
        if (!empty($action)) {
            foreach ($tmp as $k => $v) {
                $children = self::mixFormat($action, $v['id']);
                if (!empty($children)) {
                    $tmp[$k]['children'] = $children;
                }
            }
        }
        return $tmp;
    }
}
